-
Notifications
You must be signed in to change notification settings - Fork 0
feat: integrate tinyfish dify plugin #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughThis PR adds a TinyFish Web Agent plugin for Dify: provider and credential validation, a shared TinyfishMixin API client, five tools (RunSync, RunAsync, RunSSE, ListRuns, GetRun) with robust HTTP and error handling, manifest and provider YAMLs, docs/localization, CI workflow for packaging/publishing, example env and ignore files, a minimal plugin entrypoint, and a LICENSE. It also adds API_BASE_URL and a dify_plugin dependency. Sequence Diagram(s)sequenceDiagram
participant Agent as Dify Agent/Workflow
participant Tool as Tool Implementation
participant API as TinyFish Web Agent API
participant Runtime as Dify Runtime
rect rgba(100, 150, 255, 0.5)
Note over Agent,Runtime: Synchronous Execution (RunSyncTool)
Agent->>Tool: _invoke(url, goal, browser_profile, proxy_config)
Tool->>Runtime: Retrieve api_key from credentials
Tool->>Tool: Build automation payload
Tool->>API: POST /v1/automation/run (timeout: 300s)
API-->>Tool: Response with status & result
Tool->>Tool: Parse status (COMPLETED/FAILED/OTHER)
Tool-->>Agent: Emit result messages + JSON payload
end
rect rgba(100, 255, 150, 0.5)
Note over Agent,Runtime: Asynchronous Execution (RunAsyncTool)
Agent->>Tool: _invoke(url, goal, browser_profile, proxy_config)
Tool->>Runtime: Retrieve api_key from credentials
Tool->>Tool: Build automation payload
Tool->>API: POST /v1/automation/run-async
API-->>Tool: Response with run_id
Tool-->>Agent: Emit run_id + guidance message
end
rect rgba(255, 200, 100, 0.5)
Note over Agent,Runtime: Server-Sent Event Streaming (RunSseTool)
Agent->>Tool: _invoke(url, goal, browser_profile, proxy_config)
Tool->>Runtime: Retrieve api_key from credentials
Tool->>Tool: Build automation payload
Tool->>API: Open SSE stream to /v1/automation/run-sse
loop Event Stream Processing
API-->>Tool: Event (STARTED/STREAMING_URL/PROGRESS/COMPLETE)
Tool->>Tool: Parse event data
Tool-->>Agent: Emit corresponding message
end
Tool-->>Agent: Close stream + final JSON result
end
rect rgba(200, 100, 255, 0.5)
Note over Agent,Runtime: Polling & Listing (GetRunTool / ListRunsTool)
Agent->>Tool: _invoke(run_id or filters)
Tool->>Runtime: Retrieve api_key from credentials
Tool->>API: GET /v1/runs/{run_id} or GET /v1/runs?params
API-->>Tool: Response with run data/status
Tool->>Tool: Parse response (status, metadata)
Tool-->>Agent: Emit status/list messages + JSON payload
end
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
🤖 Fix all issues with AI agents
In `@dify/.env.example`:
- Around line 1-3: Reorder the keys in .env.example so they are alphabetically
ordered to satisfy dotenv-linter: change the sequence from INSTALL_METHOD,
REMOTE_INSTALL_URL, REMOTE_INSTALL_KEY to INSTALL_METHOD, REMOTE_INSTALL_KEY,
REMOTE_INSTALL_URL; update only the ordering of the three variables
(INSTALL_METHOD, REMOTE_INSTALL_KEY, REMOTE_INSTALL_URL) without changing their
values.
In `@dify/.github/workflows/plugin-publish.yml`:
- Around line 82-83: The branch name used when creating the branch
(BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{
steps.get_basic_info.outputs.version }}"; git checkout -b "$BRANCH_NAME") does
not match the branch referenced later when creating the PR; update either the
branch creation or the PR head to use the same convention: change the
BRANCH_NAME format to match the PR head (e.g., "${{
steps.get_basic_info.outputs.plugin_name }}-${{
steps.get_basic_info.outputs.version }}") or change the PR head to "bump-${{
steps.get_basic_info.outputs.plugin_name }}-plugin-${{
steps.get_basic_info.outputs.version }}", making sure all references to
BRANCH_NAME and the gh pr create head/head_ref use the identical string (use the
BRANCH_NAME variable to populate the PR head to avoid future mismatches).
In `@dify/GUIDE.md`:
- Around line 98-102: The fenced code block containing INSTALL_METHOD,
REMOTE_INSTALL_URL, and REMOTE_INSTALL_KEY needs a language specifier for syntax
highlighting and accessibility; change the opening triple backticks for that
block from ``` to ```bash so the block explicitly specifies bash/sh and renders
correctly.
- Line 115: The "Manual Packaging" heading currently uses four hashes (####
Manual Packaging) which jumps two levels from the surrounding h2; change that
heading to three hashes (### Manual Packaging) so the heading level increments
by a single level and matches the document structure.
In `@dify/README.md`:
- Line 22: The Markdown images lack alt text; update each image markdown (e.g.,
the line with "" and the other image lines at
the same locations) to include concise, descriptive alt text inside the brackets
(for example replace "" with ""), and do the same for the images at lines
32, 63 and 81 so all four images have meaningful alt attributes.
- Line 14: Replace the incorrect indefinite article in the heading "Create an
TinyFish Web Agent API Key" by changing "an" to "a" so the header reads "Create
a TinyFish Web Agent API Key"; update the heading text in README.md (the line
containing "Create an TinyFish Web Agent API Key") accordingly.
In `@dify/readme/README_ja_JP.md`:
- Around line 1-3: Replace the placeholder Japanese README content under the "##
プラグイン Readme" header with a localized, meaningful description or a link to the
canonical README; specifically update the line currently reading
"ここに詳細なプラグイン説明ドキュメントを記載してください。" to provide either a full Japanese summary of the
plugin (purpose, usage, configuration, links) or a clear link to the main README
so the shipped package does not contain empty placeholder text.
In `@dify/readme/README_pt_BR.md`:
- Around line 1-3: The Portuguese README (README_pt_BR.md) is just a placeholder
and must be removed or replaced with a proper Brazilian Portuguese translation;
either delete README_pt_BR.md if localized docs aren't ready, or populate it by
translating the main README.md (and GUIDE.md where relevant) into clear
Brazilian Portuguese, preserving headings, code blocks, table of contents,
links, and any metadata so the translated file matches the original structure
and content.
In `@dify/readme/README_zh_Hans.md`:
- Around line 1-3: The README_zh_Hans.md currently contains a placeholder
(“请在这里填写详细的插件说明文档。”); replace that placeholder text with a proper Chinese
localization of the plugin README (detailing purpose, installation, usage,
config, and links) or, if translation isn’t ready, insert a clear link to the
canonical README and a note pointing to where localized docs will be added;
update the header and body in README_zh_Hans.md so no placeholder lines remain.
In `@dify/tools/run_sse.py`:
- Around line 71-93: The redundant end-of-run message occurs because
final_result is None for failed COMPLETE events but you still emit the generic
"Automation ended without returning a result" after handling COMPLETE; modify
the SSE handler to track completion explicitly (e.g., a boolean like
seen_complete or completed_flag) when event_type == "COMPLETE" and set it in
both the COMPLETED and non-COMPLETED branches, then only emit the trailing
create_text_message("Automation ended without returning a result") if
seen_complete is False (or if no COMPLETE was received) and final_result is
None; update references in this flow to event_type, status, final_result,
create_text_message and create_json_message so failed runs only show the failure
message and not the extra “ended without returning a result” message.
🧹 Nitpick comments (5)
dify/main.py (1)
1-6: Consider env-based configuration for MAX_REQUEST_TIMEOUT for operational flexibility.The current hardcoded 120s is appropriate for SDK-level HTTP requests (e.g., OpenAI API calls); note that tool execution timeouts are separately configured (e.g.,
run_sse.pyuses explicit 300.0s for SSE streams). Making this configurable via environment variable follows standard practice for containerized deployments.⚙️ Optional env-based configuration
-from dify_plugin import Plugin, DifyPluginEnv +import os +from dify_plugin import Plugin, DifyPluginEnv -plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120)) +timeout = int(os.getenv("DIFY_MAX_REQUEST_TIMEOUT", "120")) +plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=timeout))dify/tools/get_run.py (1)
40-64: Duplicate JSON output may confuse downstream consumers.When the status is
COMPLETEDandresult["result"]exists, two JSON messages are emitted: one with just the result payload (line 43) and another with the full response object (line 64). This could lead to redundant data in the output stream.Consider whether the final
create_json_message(result)at line 64 should be conditional (e.g., only emit if result wasn't already yielded), or clarify the intent with a comment if both are intentional for different consumers.dify/.github/workflows/plugin-publish.yml (2)
14-24: CLI tool download lacks integrity verification.The CLI binary is downloaded directly without checksum or signature verification. This is a supply chain security concern—if the download URL is compromised or MITM'd, malicious code could be executed in the workflow.
Consider adding checksum verification after download:
🔒 Proposed fix to add checksum verification
wget https://github.com/langgenius/dify-plugin-daemon/releases/download/0.0.6/dify-plugin-linux-amd64 + # Verify checksum (replace with actual sha256 from release) + echo "EXPECTED_SHA256_HERE dify-plugin-linux-amd64" | sha256sum -c - chmod +x dify-plugin-linux-amd64
26-40: Manifest parsing is fragile and may fail on quoted or multi-space values.The
grep | cutapproach assumes values have exactly one space after the colon and no quotes. Values likename: "my-plugin"orname: my-plugin(double space) will produce incorrect results.Consider using
yqfor robust YAML parsing:♻️ Proposed fix using yq for robust parsing
- name: Get basic info from manifest id: get_basic_info run: | - PLUGIN_NAME=$(grep "^name:" manifest.yaml | cut -d' ' -f2) + PLUGIN_NAME=$(yq -r '.name' manifest.yaml) echo "Plugin name: $PLUGIN_NAME" echo "plugin_name=$PLUGIN_NAME" >> $GITHUB_OUTPUT - VERSION=$(grep "^version:" manifest.yaml | cut -d' ' -f2) + VERSION=$(yq -r '.version' manifest.yaml) echo "Plugin version: $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT - AUTHOR=$(grep "^author:" manifest.yaml | cut -d' ' -f2) + AUTHOR=$(yq -r '.author' manifest.yaml) echo "Plugin author: $AUTHOR" echo "author=$AUTHOR" >> $GITHUB_OUTPUTNote: You may need to install
yqfirst or usepython -c "import yaml; ..."as an alternative.dify/tools/run_async.yaml (1)
72-84: Minor: Inconsistent option labels compared torun_sse.yaml.The browser profile options here use short labels (
"Lite","Stealth") whilerun_sse.yamluses more descriptive labels ("Lite (Standard Browser)","Stealth (Anti-Detection)"). Consider aligning these for a consistent user experience across tools.♻️ Proposed fix to align labels with run_sse.yaml
options: - value: "lite" label: - en_US: "Lite" - zh_Hans: "Lite" - pt_BR: "Lite" - ja_JP: "Lite" + en_US: "Lite (Standard Browser)" + zh_Hans: "Lite(标准浏览器)" + pt_BR: "Lite (Navegador Padrão)" + ja_JP: "Lite(標準ブラウザ)" - value: "stealth" label: - en_US: "Stealth" - zh_Hans: "Stealth" - pt_BR: "Stealth" - ja_JP: "Stealth" + en_US: "Stealth (Anti-Detection)" + zh_Hans: "Stealth(反检测)" + pt_BR: "Stealth (Anti-Detecção)" + ja_JP: "Stealth(検出防止)"
| BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}" | ||
| git checkout -b "$BRANCH_NAME" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Branch name mismatch will cause PR creation to fail.
The branch pushed at line 83 is named bump-{plugin_name}-plugin-{version}, but the PR head at line 103 references {plugin_name}-{version} (without the bump- prefix and -plugin suffix). This mismatch will cause the gh pr create command to fail with a "branch not found" error.
🐛 Proposed fix to align branch names
gh pr create \
--repo langgenius/dify-plugins \
- --head "${{ steps.get_basic_info.outputs.author }}:${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}" \
+ --head "${{ steps.get_basic_info.outputs.author }}:bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}" \
--base main \Also applies to: 101-103
🤖 Prompt for AI Agents
In `@dify/.github/workflows/plugin-publish.yml` around lines 82 - 83, The branch
name used when creating the branch (BRANCH_NAME="bump-${{
steps.get_basic_info.outputs.plugin_name }}-plugin-${{
steps.get_basic_info.outputs.version }}"; git checkout -b "$BRANCH_NAME") does
not match the branch referenced later when creating the PR; update either the
branch creation or the PR head to use the same convention: change the
BRANCH_NAME format to match the PR head (e.g., "${{
steps.get_basic_info.outputs.plugin_name }}-${{
steps.get_basic_info.outputs.version }}") or change the PR head to "bump-${{
steps.get_basic_info.outputs.plugin_name }}-plugin-${{
steps.get_basic_info.outputs.version }}", making sure all references to
BRANCH_NAME and the gh pr create head/head_ref use the identical string (use the
BRANCH_NAME variable to populate the PR head to avoid future mismatches).
… and redirect the Portuguese version to the main README.
Summary
Implementation
Core logic (
tools/)tools/run_sync.pytools/run_async.pyrun_idimmediately for pollingtools/run_sse.pytools/get_run.pytools/list_runs.pytools/constants.pyBoilerplate / config
manifest.yamlprovider/tinyfish_web_agent.pyprovider/tinyfish_web_agent.yamltools/*.yamlmain.py.github/workflows/plugin-publish.ymlGUIDE.md,README.md,PRIVACY.md,readme/Demo
Screen.Recording.2026-02-07.at.8.34.54.PM.mov
goalandurlfrom the user query. Since our API does not support raw query.run_asyncto execute the run and pollget-runfor the status and the final result.How to Install Dify
Test plan